package com.nameless.config;

import com.alibaba.fastjson.JSON;
import com.nameless.service.UserService;
import com.nameless.util.JwtUtil;
import com.nameless.vo.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

import java.io.PrintWriter;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author WHZ
 * @date 2023年03月02日 10:15
 */
@Configuration
@SuppressWarnings("all")
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserService userService;

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
    }
    @Value("${pass.whiteListPhone}")
    private String[] path;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                // 对于登录login 注册register 验证码captchaImage 允许匿名访问
                .antMatchers("/login1").permitAll()
                .antMatchers(path).permitAll()
                // 静态资源，可匿名访问
                .antMatchers("/doc.html","/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/csrf", "/v2/*","/register","/banner").permitAll()
                .antMatchers("/").permitAll();

        http.formLogin().loginProcessingUrl("/login1")
                .failureHandler(failureHandler())
                .successHandler(successHandler()).permitAll();
        http.cors();
        http.csrf().disable();
        http.authorizeRequests().anyRequest().authenticated();
    }

    private AuthenticationFailureHandler failureHandler(){
        return (request, response, exception)->{
            response.setContentType("application/json;charset=utf-8");
            PrintWriter writer = response.getWriter();

            Result<String> result=new Result<>(500,"登录失败");
            String jsonString = JSON.toJSONString(result);

            writer.print(jsonString);
            writer.flush();
            writer.close();
        };
    }

    private AuthenticationSuccessHandler successHandler(){
        return ( request, response, authentication)->{
            response.setContentType("application/json;charset=utf-8");
            PrintWriter writer = response.getWriter();

            //获取用户的信息
            User user = (User) authentication.getPrincipal();
            //获取账户名
            String username = user.getUsername();
            //获取权限
            Collection<GrantedAuthority> authorities = user.getAuthorities();
            List<String> permission = authorities.stream().map(item -> item.getAuthority()).collect(Collectors.toList());
            Map<String, Object> map = new HashMap<>();
            map.put("clientname",username);
            map.put("permission",permission);
            String token = JwtUtil.createJWT(map);
            stringRedisTemplate.opsForValue().set(token,"",1, TimeUnit.DAYS);
            Result<String> result=new Result<>(200,"登录成功",token);
            String jsonString = JSON.toJSONString(result);

            writer.print(jsonString);
            writer.flush();
            writer.close();
        };
    }
}
